package tests.jdl.tokenization.states;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import jdl.tokenization.Token;
import jdl.tokenization.TokenType;
import jdl.tokenization.states.IState;
import jdl.tokenization.states.InitialState;
import jdl.tokenization.states.NumberState;
import jdl.tokenization.states.WordState;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

public class WordState_Test {
	private List<Token> tokens;
	private Hashtable<Character, TokenType> hashtable;
	private IState state;

	@Before
	public void setUp() {
		tokens = new ArrayList<Token>();
		hashtable = new Hashtable<Character, TokenType>();
		hashtable.put('4', TokenType.NUMBER);
		hashtable.put('7', TokenType.NUMBER);
		hashtable.put('(', TokenType.LEFT_BRACKET);
		state = new WordState(tokens, hashtable);
	}

	@Test
	public void analyzeSymbol_symbolIsLetter_checkNextState() {
		state.analyzeSymbol('r');
		Assert.assertEquals(state, state.getNextState());
	}

	@Test
	public void analyzeSymbol_symbolIsLetter_endOfSymbols() {
		state.analyzeSymbol('r');
		state.endOfSymbols();

		Assert.assertEquals(1, tokens.size());
		Token token = tokens.get(0);
		Assert.assertEquals(TokenType.WORD, token.getTokenType());
		Assert.assertEquals("r", token.getContent());
	}

	@Test
	public void analyzeSymbol_symbolIsNumber() {
		state.analyzeSymbol('4');
		Assert.assertTrue(state.getNextState() instanceof NumberState);
	}

	@Test
	public void analyzeSymbol_symbolIsLetter_analyzeSymbol_symbolIsLetter_endOfSymbols() {
		state.analyzeSymbol('b');
		state.analyzeSymbol('e');

		state.endOfSymbols();

		Assert.assertEquals(1, tokens.size());
		Token token = tokens.get(0);
		Assert.assertEquals(TokenType.WORD, token.getTokenType());
		Assert.assertEquals("be", token.getContent());
	}

	@Test
	public void analyzeSymbol_symbolIsLetter_analyzeSymbol_symbolIsNumber_endOfSymbols() {
		state.analyzeSymbol('g');
		state.analyzeSymbol('7');
		state.endOfSymbols();

		Assert.assertEquals(1, tokens.size());
		Token token = tokens.get(0);
		Assert.assertEquals(TokenType.WORD, token.getTokenType());
		Assert.assertEquals("g7", token.getContent());
	}

	@Test
	public void analyzeSymbol_symbolIsLetter_analyzeSymbol_symbolIsLeftBracket() {
		state.analyzeSymbol('h');
		state.analyzeSymbol('(');

		Assert.assertEquals(2, tokens.size());
		Token token = tokens.get(0);
		Assert.assertEquals(TokenType.WORD, token.getTokenType());
		Assert.assertEquals("h", token.getContent());

		token = tokens.get(1);
		Assert.assertEquals(TokenType.LEFT_BRACKET, token.getTokenType());
		Assert.assertEquals("(", token.getContent());
	}

	@Test
	public void analyzeSymbol_symbolIsLeftBracket() {
		state.analyzeSymbol('(');
		Assert.assertTrue(state.getNextState() instanceof InitialState);
	}

	@Test
	public void analyzeSymbol_symbolIsLetter_getNextState_analyzeSymbol_symbolIsWhiteSpace_getNextState_endOfSymbols() {
		state.analyzeSymbol('a');
		state = state.getNextState();
		state.analyzeSymbol(' ');
		state = state.getNextState();
		state.endOfSymbols();

		Assert.assertEquals(1, tokens.size());

		Token token = tokens.get(0);
		Assert.assertEquals(TokenType.WORD, token.getTokenType());
		Assert.assertEquals("a", token.getContent());
	}

	@Test
	public void analyzeSymbol_symbolIsLetter_analyzeSymbol_symbolIsWhiteSpace() {
		state.analyzeSymbol('a');
		state.analyzeSymbol(' ');

		Assert.assertEquals(1, tokens.size());

		Token token = tokens.get(0);
		Assert.assertEquals(TokenType.WORD, token.getTokenType());
		Assert.assertEquals("a", token.getContent());
	}
}
